# -*- coding: utf-8 -*-

from .zncspt import API
from . import odoo_fields as fields
import json

import logging

_logger = logging.getLogger(__name__)


class BaseModel(object):
    @classmethod
    def value_get(cls, record):
        one = {}
        for fld, val in record.items():
            if hasattr(cls, fld):
                meta = getattr(cls, fld)
                one[meta.field_name] = meta.value_get(val)
        return one


class OdooFapiao(BaseModel):
    # 查验发票时, 从 odoo 来的数据, 转换为 API接口 需要的格式
    # 对应 fp.fapiao

    invoice_type = fields.Selection(selection=[
        ('vat_special', '01'),  # 增值税专用发票
        ('vat_traffic', '02'),  # 货物运输业增值税专用发票
        ('vat_vehicle', '03'),  # 机动车销售统一发票
        ('vat_general', '04'),  # 增值税普通发票
        ('vat_general_e', '10'),  # 增值税普通发票(电子)
        ('vat_general_roll', '11'),  # 增值税普通发票(卷式)
        ('vat_toll', '14'),  # 通行费发票
        ('vat_vehicle_2', '15'),  # 二手车发票
        ('vat_special_e', '08'),  # 增值税电子专用发票
        ('vat_block_chain', '16'),  # 区块链电子发票 只支持深圳地区
        ('vat_special_ex', '21'),  # 全电专票
        ('vat_general_ex', '22'),  # 全电普票

    ], string="发票种类", field_name='fpzl')

    invoice_code = fields.Char('发票代码', 'fpdm')
    invoice_number = fields.Char('发票号码', 'fphm')
    check_code = fields.Char('校验码', 'jym', help='取后六位')
    amount_total = fields.Char('价税合计', 'fpje')
    date_fapiao = fields.Char('开票日期', 'kprq', help='yyyymmdd格式')

    @classmethod
    def prepare_create(cls, record):

        check_code = record['check_code']
        if check_code:
            record['check_code'] = check_code[-6:]

        order = cls.value_get(record)
        return order


class ApiFapiaoLine(BaseModel):
    # 查验发票成功后, 发票数据, 写入 odoo 前. 转换为 odoo 需要的格式
    # 对应 fp.fapiao.line

    mxbh = fields.Integer('明细行号', 'row_number')
    ssflbm = fields.Char('税收分类编码', 'vat_product_code')
    hwmc = fields.Char('货物名称', 'product_name')  # *税收分类名称*商品名称
    ggxh = fields.Char('规格型号', 'product_spec')
    jldw = fields.Char('计量单位', 'product_uom')

    sl = fields.Float('税率', 'tax_ratio')  # 13%

    spsl = fields.Float('数量', 'quantity')  # 1.123345678
    bhsdj = fields.Float('不含税单价', 'price_untax')  # 1.123456677

    hsdj = fields.Float('含税单价', 'price_unit')  # 无

    je = fields.Float('不含税金额', 'amount_untaxed')  # 100.12
    se = fields.Float('税', 'amount_tax')  # 13.03
    hsje = fields.Float('含税金额', 'amount_total')  # 无

    @classmethod
    def value_get(cls, record):

        def get_sl():
            sl = record.get('sl')
            if sl and sl[-1] == '%':
                return sl[:-1]
            else:
                return '0'

        def split_product_name():
            pname = one['product_name']
            if not pname:
                return '', ''

            if pname[0] != '*':
                return '', pname

            ps = pname[1:].split('*')

            if len(ps) < 2:
                return '', pname

            return ps[0], '*'.join(ps[1:])

        def get_amount_total():
            amount_untaxed = one['amount_untaxed']
            amount_tax = one['amount_tax']
            amount_total = one['amount_total']

            if not amount_total:
                amount_total = amount_untaxed + amount_tax
                amount_total = round(amount_total, 2)

            return amount_total

        def get_price_unit():
            quantity = one['quantity']
            price_unit = one['price_unit']
            amount_total = one['amount_total']

            # price_untax = one['price_untax']
            # tax_ratio = one['tax_ratio'] / 100

            if not price_unit:
                if quantity:
                    price_unit = amount_total / quantity
                    price_unit = round(price_unit, 2)
                else:
                    price_unit = 0.0

            return price_unit

        record['sl'] = get_sl()
        one = super().value_get(record)

        vat_product_name, product_name = split_product_name()
        one['vat_product_name'] = vat_product_name
        one['product_name'] = product_name
        one['amount_total'] = get_amount_total()
        one['price_unit'] = get_price_unit()
        one['name'] = product_name

        return one


class ApiFapiao(BaseModel):
    # 查验成功后, 读取发票数据, 写入 odoo 前. 转换为 odoo 需要的格式
    # 对应 fp.fapiao

    fpzl = fields.Selection(
        selection=[
            ('01', 'vat_special'),  # 增值税专用发票
            ('02', 'vat_traffic'),  # 货物运输业增值税专用发票
            ('03', 'vat_vehicle'),  # 机动车销售统一发票
            ('04', 'vat_general'),  # 增值税普通发票
            ('10', 'vat_general_e'),  # 增值税普通发票(电子)
            ('11', 'vat_general_roll'),  # 增值税普通发票(卷式)
            ('14', 'vat_toll'),  # 通行费发票
            ('15', 'vat_vehicle_2'),  # 二手车发票
            ('08', 'vat_special_e'),  # 增值税电子专用发票
            ('16', 'vat_block_chain'),  # 区块链电子发票 只支持深圳地区
            ('21', 'vat_special_ex'),  # 全电专票
            ('22', 'vat_general_ex'),  # 全电普票
        ],
        string="发票种类", field_name='invoice_type')

    jqbh = fields.Char('机器编号', 'taxmachine_code')
    fpdm = fields.Char('发票代码', 'invoice_code')
    fphm = fields.Char('发票号码', 'invoice_number')
    jym = fields.Char('校验码', 'check_code')

    xhfmc = fields.Char('销售方名称', 'saler_name')
    xhfsbh = fields.Char('销售方识别号', 'saler_tin')
    xhfdzdh = fields.Char('销售方地址电话', 'saler_address_phone')
    xhfyhzh = fields.Char('销售方银行账号', 'saler_bank_account')

    gmfmc = fields.Char('购买方名称', 'buyer_name')
    gmfsbh = fields.Char('购买方识别号', 'buyer_tin')
    gmfdzdh = fields.Char('购买方地址电话', 'buyer_address_phone')
    gmfyhzh = fields.Char('购买方银行账号', 'buyer_bank_account')

    bz = fields.Char('备注', 'note')

    kpr = fields.Char('开票人', 'drawer_name')
    skr = fields.Char('收款人', 'payee_name')
    fhr = fields.Char('复核', 'checker_name')

    kprq = fields.DateYYYYMMDD('开票时间', 'date_fapiao')

    fpse = fields.Float('税额', 'amount_tax')
    jshj = fields.Float('含税金额', 'amount_total')
    fpje = fields.Float('不含税金额', 'amount_untaxed')

    # 以上是 票面信息

    # 以下是 查验接口状态信息
    # 查验时间?  一天5次
    cycs = fields.Integer('查验次数', 'api_check_count')

    cyjg = fields.Selection(
        selection=[
            ('9999', 'api_error_9999'),  # 查验失败
            ('0001', 'done'),  # 查验成功发票一致
            ('0002', 'api_error_0002'),  # 超过该张票当天查验次数
            ('0005', 'fpi_error_0005'),  # 请求不合法. 发票信息有误，请核对后再查询
            ('0006', 'fpi_error_0006'),  # 发票信息不一致. 发票信息有误，请核对后再查询
            ('0009', 'fpi_error_0009'),  # 发票不存在. 所查发票不存在
            ('1004', 'api_error_1004'),  # 已超过最大查验量. 已超过最大查验量，请联系管理员
            ('1005', 'fpi_error_1005'),  # 查询发票不规范. 信息有误，请核对后再查询
            ('1006', 'fpi_error_1006'),  # 查验异常. 发票信息有误，请核对后再查询
            ('1007', 'api_error_1007'),  # 该批次已过期，请重新更换批次号查验
            ('1008', 'api_error_1008'),  # 字段不能为空. 发票请求参数不能为空
            ('1009', 'api_error_1009'),  # 参数长度不正确. 参数长度不符合规范，确认参数，再次查验
            ('1010', 'api_error_1010'),  # 当前查验未完成. 查验正在进行中(批量查验)
            ('1011', 'api_error_1011'),  # 该批次已查验. 批量已查验(应当调用发票获取接口 获得查验发票信息)
            ('1012', 'api_error_1012'),  # 超过规定张数. 批量查验接口默认 200 张，超过 规定张数
            ('1013', 'api_error_1013'),  # 批次号不存在. 可重新请求，换批次号
            ('1014', 'api_error_1014'),  # 日期当天的不能查验. 日期当天的不能查验，请隔天再查
            ('1015', 'api_error_1015'),  # 超过 5 年的不能查验. 超过 5 年的不能查验
            ('1020', 'api_error_1020'),  # 没有查验权限. 没有查验权限，请联系管理员
            ('1021', 'api_error_1021'),  # 网络超时. 税局维护升级
        ],
        string="查验结果", field_name='api_check_result')

    cyjgxx = fields.Char('查验结果信息', 'api_check_result_info')

    zfbz = fields.Selection(
        selection=[
            ('N', 'done'),  # 正常
            ('H', 'refunded'),  # 已冲红
            ('Y', 'be_invalid'),  # 已作废
        ],
        string="作废标志", field_name='state')

    qdbz = fields.Char('清单标志', 'api_list_flag', help='Y:带清单, N:无清单')

    detailList = fields.One2many(ApiFapiaoLine, '明细行', 'line_ids')

    @classmethod
    def value_get(cls, record):

        cyjg = record['cyjg']
        cyjgxx = record['cyjgxx']

        if cyjg == '0001':
            one = super().value_get(record)
        else:
            one = super().value_get({
                'cyjg': cyjg,
                'cyjgxx': cyjgxx
            })

        # 销售方地址电话 = addres + phone
        # 销售方银行账号 = bank_name + acc_nuber

        # 购买方地址电话 = addres + phone
        # 购买方银行账号 = bank_name + acc_nuber

        return one

    @classmethod
    def after_read(cls, records):
        return [cls.value_get(record) for record in records]


class OdooApi(API):
    def check_one(self, record):
        content = OdooFapiao.prepare_create(record)
        # print('check one 1,', content)
        res = self.check_invoice_single(content)
        # print('check one 2,', res)

        _logger.info('check fapiao ok, %s',  res)

        records2 = ApiFapiao.after_read([res])
        # print('check one 3ok,', records2[0])

        return {'result': records2[0]}
